home *** CD-ROM | disk | FTP | other *** search
- /*
- File: CalcController.m
-
- Contains: xxx
-
- Written by: Andy Wildenberg
-
- Created: Wed 09-Jul-1997
-
- Copyright: (c)1997 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
- 7/5/00 KG Updated for Project Builder on DP4
- 9 July 97 -- first version of application
-
- You may incorporate this sample code into your applications without
- restriction, though the sample code has been provided "AS IS" and the
- responsibility for its operation is 100% yours. However, what you are
- not permitted to do is to redistribute the source as "DSC Sample Code"
- after having made changes. If you're going to re-distribute the source,
- we require that you make it clear in the source that the code was
- descended from Apple Sample Code, but that you've made changes.
- */
-
- #import "CalcController.h"
-
- @implementation CalcController
-
- - (void)clear:(id)sender
- {
- [displayedNumber autorelease];
- displayedNumber = [[NSDecimalNumber zero] retain];
- [enteredNumber autorelease];
- enteredNumber = [[NSDecimalNumber zero] retain];
- [displayView setDoubleValue: 0];
- [self endEditingNumber];
- lastOperation = kNoOperator;
- usedDecimalPoint = NO;
- }
-
- - (void)equals:(id)sender
- {
- if (enteringNumber)
- {
- [self endEditingNumber];
- [self performLastOperation];
- lastOperation = kNoOperator;
- [displayView setStringValue: [displayedNumber stringValue]];
- }
- }
-
- - (void)insertDigit:(id)sender
- {
- NSString* oldValue;
-
- if (!enteringNumber)
- {
- [self beginEditingNumber];
- }
-
-
- oldValue = [displayView stringValue];
- [displayView setStringValue: [oldValue stringByAppendingString: [sender title]]];
- }
-
- - (void)beginEditingNumber
- {
- enteringNumber = YES;
- usedDecimalPoint = NO;
- [displayView setStringValue: @""];
- [enteredNumber autorelease];
- enteredNumber = [displayedNumber copy];
- }
-
- - (void)endEditingNumber
- {
- enteringNumber = NO;
- usedDecimalPoint = NO;
-
- [displayedNumber autorelease];
- displayedNumber = [NSDecimalNumber decimalNumberWithString: [displayView stringValue]];
- [displayedNumber retain];
- }
-
- - (void)decimalPoint:(id)sender
- {
- NSString* oldValue;
-
- if (!usedDecimalPoint)
- {
- usedDecimalPoint = YES;
- if (!enteringNumber)
- {
- [self beginEditingNumber];
- [displayView setStringValue: @"0."];
- }
- else
- {
- oldValue = [displayView stringValue];
- [displayView setStringValue: [oldValue stringByAppendingString: @"."]];
- }
- }
- }
-
- -(void) awakeFromNib
- {
- [self clear: self];
- [[displayView window] makeKeyAndOrderFront:nil];
- }
-
- - (void)operation:(id)sender
- {
- if (enteringNumber)
- {
- [self endEditingNumber];
- [self performLastOperation];
- [displayView setStringValue: [displayedNumber stringValue]];
- }
- // no matter what, set the new operation in case the user changes his/her mind
- lastOperation = [sender tag];
-
- }
-
- - (void)performLastOperation
- {
- if (lastOperation == kNoOperator)
- {
- return;
- }
-
- // it is possible to extensively rewrite the following code. In all cases,
- // displayedNumber is autoreleased, assigned a new value and that new value is
- // retained. Thus it would reduce the number of lines of code to put the
- // autorelease statement before the nest of if statements, and put the retain
- // statement after the nest of if statements. However, I've duplicated the
- // statements just to brutally drive home the point that you need to autorelease
- // before you assign over your instance variables, and you need to retain them
- // after you've assigned to them. Even in the case that none of the if statements
- // are executed, autoreleaseing and immediately retaining the same object is
- // perfectly acceptable.
-
- // This way of detecting NANs is a HACK! Unfortunately, NaN is not ordered, so
- // if you ask any number if it's equal to NaN, it'll say yes. So, instead we'll
- // ask if it's equal to an impossible combination of numbers -- zero and one.
- // The only 'number' equal to both is NaN
- if ((([displayedNumber compare: [NSDecimalNumber zero]] == NSOrderedSame) &&
- ([displayedNumber compare: [NSDecimalNumber one]] == NSOrderedSame)) ||
- (([enteredNumber compare: [NSDecimalNumber zero]] == NSOrderedSame) &&
- ([enteredNumber compare: [NSDecimalNumber one]] == NSOrderedSame)))
- {
- [displayedNumber autorelease];
- displayedNumber = [[NSDecimalNumber notANumber] retain];
- return;
- }
- else if (lastOperation == kAddOperator)
- {
- [displayedNumber autorelease];
- displayedNumber = [enteredNumber decimalNumberByAdding: displayedNumber];
- [displayedNumber retain];
- }
- else if (lastOperation == kSubtractOperator)
- {
- [displayedNumber autorelease];
- displayedNumber = [enteredNumber decimalNumberBySubtracting: displayedNumber];
- [displayedNumber retain];
- }
- else if (lastOperation == kMultiplyOperator)
- {
- [displayedNumber autorelease];
- displayedNumber = [enteredNumber decimalNumberByMultiplyingBy: displayedNumber];
- [displayedNumber retain];
- }
- else if (lastOperation == kDivideOperator)
- {
- if ([displayedNumber compare: [NSDecimalNumber zero]] != NSOrderedSame)
- {
- [displayedNumber autorelease];
- displayedNumber = [enteredNumber decimalNumberByDividingBy: displayedNumber];
- [displayedNumber retain];
- }
- else
- {
- [displayedNumber autorelease];
- displayedNumber = [[NSDecimalNumber notANumber] retain];
- [displayedNumber retain];
- }
- }
- }
-
- - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
- {
- return YES;
- }
-
- - (void)cut:(id)sender
- {
- [self copy: self];
- [self clear: self];
- }
-
- - (void)copy:(id)sender
- {
- NSPasteboard* pasteboard = [NSPasteboard generalPasteboard];
- [pasteboard declareTypes: [NSArray arrayWithObject: NSStringPboardType] owner: NULL];
- [pasteboard setString: [displayView stringValue] forType: NSStringPboardType];
- }
-
- - (void)paste:(id)sender
- {
- NSPasteboard* pasteboard;
- NSString* pasteValue;
-
- if (!enteringNumber)
- {
- [self beginEditingNumber];
- }
-
- pasteboard = [NSPasteboard generalPasteboard];
- pasteValue = [pasteboard stringForType: NSStringPboardType];
- [displayView setStringValue: [[displayView stringValue] stringByAppendingString: pasteValue]];
- }
-
- // when self is released, it is necessary to release all of the variables we've retained
- -(void)dealloc
- {
- [displayedNumber release];
- [enteredNumber release];
- }
-
- @end
-